using System;
using System.Collections;
using System.Reflection.Emit;

namespace Evaluant.Uss.ObjectContext.Descriptors {

	/// <summary>
	/// Helper class dedicated to PersistentDescriptor
	/// </summary>
	abstract class DescriptorHelper {

		private static ArrayList _StandardTypes = new ArrayList();
		private static Hashtable _OpCodes = new Hashtable();

		static DescriptorHelper () 
		{
			_StandardTypes.Add(typeof(sbyte));
			_StandardTypes.Add(typeof(byte));
			_StandardTypes.Add(typeof(char));
			_StandardTypes.Add(typeof(short));
			_StandardTypes.Add(typeof(ushort));
			_StandardTypes.Add(typeof(int));
			_StandardTypes.Add(typeof(uint));
			_StandardTypes.Add(typeof(long));
			_StandardTypes.Add(typeof(ulong));
			_StandardTypes.Add(typeof(bool));
			_StandardTypes.Add(typeof(double));
			_StandardTypes.Add(typeof(float));
			_StandardTypes.Add(typeof(string));
			_StandardTypes.Add(typeof(DateTime));
            _StandardTypes.Add(typeof(Guid));

			_OpCodes[typeof(sbyte)] = OpCodes.Ldind_I1;
			_OpCodes[typeof(byte)] = OpCodes.Ldind_U1;
			_OpCodes[typeof(char)] = OpCodes.Ldind_U2;
			_OpCodes[typeof(short)] = OpCodes.Ldind_I2;
			_OpCodes[typeof(ushort)] = OpCodes.Ldind_U2;
			_OpCodes[typeof(int)] = OpCodes.Ldind_I4;
			_OpCodes[typeof(uint)] = OpCodes.Ldind_U4;
			_OpCodes[typeof(long)] = OpCodes.Ldind_I8;
			_OpCodes[typeof(ulong)] = OpCodes.Ldind_I8;
			_OpCodes[typeof(bool)] = OpCodes.Ldind_I1;
			_OpCodes[typeof(double)] = OpCodes.Ldind_R8;
			_OpCodes[typeof(float)] = OpCodes.Ldind_R4;
		}

		public static Hashtable OpCode
		{
			get { return _OpCodes; }
		}

		private DescriptorHelper ()
		{
		}

		/// <summary>
		/// Checks if a type is usable whithin a entity
		/// </summary>
		/// <param name="type">The type to check</param>
		/// <returns>Whether the type is usable or not</returns>
		public static bool IsEntity(Type type) 
		{
			return !(_StandardTypes.Contains(type) || type.IsEnum || type.IsArray);
		}

		/// <summary>
		/// Checks if a type is a collection
		/// </summary>
		/// <param name="type">The type to check</param>
		/// <returns>Whether the type is implements IList or not</returns>
		public static bool IsList(Type type) 
		{
			return typeof(IList).IsAssignableFrom(type);
		}

		/// <summary>
		/// Checks if a property name is valid
		/// </summary>
		/// <param name="propertyName">The property name to check</param>
		/// <returns>Whether the property name is valid or not</returns>
		public static bool IsValidProperty (string propertyName) 
		{
			return propertyName != "Entity" && propertyName != "ObjectContext" && propertyName != "Id";
		}
	}
}